package com.xz;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author：xz
 * @Date：2023/3/28
 */
public class StreamDemo {

    public static void main(String[] args) {
        List<Author> authors = getAuthors();
        test00(authors);
//        test01(authors);
//        test02();
//        test03();
//        test04();
//        test05();
//        test06();
//        test07();
//        test08();
//        test09();
//        test10();
//        test11();
//        test12();
//        test13();
//        test14();
//        test15();
//        test16();
//        test17();
//        test18();
//        test19();
//        test20();
//        test21();
//        test22();
//        test23();
//        test24();
//        test25();
//        test26();
//        testAnd();
//        testOr();
//        testMeagte();

//        Stream<Author> authorStream = getAuthors().stream();
//        authorStream.map(author -> author.getAge()).map(age -> String.valueOf(age));
//        authorStream.map(Author::getAge).map(String::valueOf);

//        StringBuilder sb = new StringBuilder();
//        authorStream.map(Author::getName).forEach(sb::append);

        // 构造器引用
        // 如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的构造方法,
        // 并且我们把要重写的抽象方法中的所有的参数都按照顺序传入了这个构造方法中,这个时候我我们就可以引用构造器。
//        List<Author> authors = getAuthors();
//        authors.stream()
//                .map(Author::getName)
//                .map(StringBuilder::new)
////                .map(new Function<StringBuilder, StringBuilder>() {
////                    @Override
////                    public StringBuilder apply(StringBuilder seq) {
////                        return new StringBuilder(seq);
////                    }
////                })
//                .map(sb -> sb.append("xz").toString())
//                .forEach(System.out::println);
//        System.out.println("================test27===============");
//        test27();
//        test28();
    }

    private static void test28() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//        Integer integer = stream.parallel()
//                .peek(new Consumer<Integer>() {
//                    @Override
//                    public void accept(Integer integer) {
//                        System.out.println(integer+":"+Thread.currentThread().getName());
//                    }
//                })
//                .filter(num -> num > 5).reduce((result, element) -> result + element).get();
//        System.out.println(integer);
        List<Author> authors = getAuthors();
        Integer integer = authors.parallelStream().map(Author::getAge)
                .peek(a -> System.out.println(a + ":" + Thread.currentThread().getName()))
                .filter(num -> num > 5).reduce((result, element) -> result + element).get();
        System.out.println(integer);
    }

    private static void test27() {
        List<Author> authors = getAuthors();
        authors.stream().distinct()
                .map(Author::getAge)
                .map(age -> age + 10)
                .filter(age -> age > 18)
                .map(age -> age + 2)
                .forEach(System.out::println);

        authors.stream().distinct()
                .mapToInt(Author::getAge)
                .map(age -> age + 10)
                .filter(age -> age > 18)
                .map(age -> age + 2)
                .forEach(System.out::println);
    }

    private static void testMeagte() {
        // 打印作家中年龄不大于17的作家
        // negate方法相当于是在判断添加前面加了个!表示取反
        List<Author> authors = getAuthors();
        authors.stream().distinct().filter(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getAge() > 17;
            }
        }.negate()).forEach(author -> System.out.println(author.getName() + ":" + author.getAge()));
    }

    private static void testOr() {
        // 打印作家中年龄大于17或者姓名的长度小于2的作家
        List<Author> authors = getAuthors();
        authors.stream().distinct().filter(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getAge() > 17;
            }
        }.or(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getName().length() < 2;
            }
        })).forEach(author -> System.out.println(author.getName() + ":" + author.getAge()));
    }

    private static void testAnd() {
        // 打印作家中年龄大于17并且姓名的长度大于1的作家
        List<Author> authors = getAuthors();
//        authors.stream().distinct().filter(author -> author.getAge() > 17 && author.getName().length() > 1).forEach(author -> System.out.println(author.getName()));
        authors.stream().distinct().filter(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getAge() > 17;
            }
        }.and(new Predicate<Author>() {
            @Override
            public boolean test(Author author) {
                return author.getName().length() > 1;
            }
        })).forEach(author -> System.out.println(author.getName() + ":" + author.getAge()));
    }

    private static void test26() {
        // 使用reduce求所有作者中年龄的最小值
        List<Author> authors = getAuthors();
        Optional<Integer> reduce = authors.stream().distinct().map(Author::getAge).reduce((result, element) -> result > element ? element : result);
        reduce.ifPresent(age -> System.out.println(age));
    }

    private static void test25() {
        // 使用reduce求所有作者中年龄的最小值
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream().distinct().map(Author::getAge).reduce(Integer.MAX_VALUE, (result, element) -> result > element ? element : result);
        System.out.println(reduce);
    }

    private static void test24() {
        // 使用reduce求所有作者中年龄的最大值
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream().distinct().map(Author::getAge).reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);
        System.out.println(reduce);

    }

    private static void test23() {
        // 使用reduce求所有作者年龄的和
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream().distinct().map(Author::getAge).reduce(0, (result, element) -> result + element);
        System.out.println(reduce);

    }

    private static void test22() {
        // 获取一个年龄最小的作家，并输出他的名字
        // 获取流中的第一个元素
        List<Author> authors = getAuthors();
        Optional<Author> first = authors.stream().distinct().sorted((a, b) -> a.getAge() - b.getAge()).findFirst();
        System.out.println(first.get().getName() + ":" + first.get().getAge());

    }

    private static void test21() {
        // 获取任意一个年龄大于18的作家，如果存在就输出他的名字
        // 获取流中的任意一个元素。该方法没有办法保证获取的一定是流中的第一个元素
        List<Author> authors = getAuthors();
        Optional<Author> any = authors.stream().filter(author -> author.getAge() > 18).findAny();
//        if (any.isPresent()) {
//            System.out.println(any.get().getName());
//        }
        any.ifPresent(author -> System.out.println(author.getName()));

    }

    private static void test20() {
        // 判断作家是否都没有超过100岁的
        // 所有数据都不符合条件才为true
        List<Author> authors = getAuthors();
        boolean noneMatch = authors.stream().noneMatch(author -> author.getAge() > 100);
        System.out.println(noneMatch);
    }

    private static void test19() {
        // 判断是否所有的作家都是成年人
        // 所有数据符合条件才为true
        List<Author> authors = getAuthors();
        boolean allMatch = authors.stream().allMatch(author -> author.getAge() > 18);
        System.out.println(allMatch);
    }

    private static void test18() {
        // 判断是否有年龄在29以上的作家
        // 任意一个符合条件就为true
        List<Author> authors = getAuthors();
        boolean anyMatch = authors.stream()
                .anyMatch(author -> author.getAge() > 46);
        System.out.println(anyMatch);
    }

    private static void test17() {
        // 获取一个Map集合，map的key为作者名，value为list<Book>
        List<Author> authors = getAuthors();
        Map<String, List<Book>> collect = authors.stream().distinct()
                .collect(Collectors.toMap(Author::getName, Author::getBooks));
        collect.forEach((a, b) -> {
            System.out.println(a + "=" + b);
        });
    }

    private static void test16() {
        // 获取一个所有书名的Set集合
        List<Author> authors = getAuthors();
        Set<String> collect = authors.stream().flatMap(author -> author.getBooks().stream()).map(Book::getName).collect(Collectors.toSet());
        System.out.println(collect);
    }

    private static void test15() {
        // 获取一个存放所有作者名字的list集合
        List<Author> authors = getAuthors();
        List<String> collect = authors.stream().map(Author::getName).distinct().collect(Collectors.toList());
        System.out.println(collect);

    }

    private static void test14() {
        // 分别获取这些作家所出数据的最高分和最低分并打印
        List<Author> authors = getAuthors();
        Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore())
                .max((o1, o2) -> o1 - o2);
        System.out.println(max.get());
        Optional<Integer> min = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore())
                .min((o1, o2) -> o1 - o2);
        System.out.println(min.get());
    }

    private static void test13() {
        // 打印这些作家所出书籍的数目，注意删除重复元素
        List<Author> authors = getAuthors();
        long count = authors.stream().distinct().flatMap(author -> author.getBooks().stream()).distinct().count();
        System.out.println(count);
    }

    private static void test12() {
        // 输出所有作家的名字
        List<Author> authors = getAuthors();
        authors.stream().map(Author::getName).distinct().forEach(System.out::println);
    }

    private static void test11() {
        // 打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式：哲学，爱情
        List<Author> authors = getAuthors();
        authors.stream().flatMap(author -> author.getBooks().stream()).distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split("，")))
                .distinct()
                .forEach(System.out::println);
    }

    private static void test10() {
        // 打印所有书籍的名字。要求对重复的元素进行去重
        List<Author> authors = getAuthors();
        // map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素
//        authors.stream().map(Author::getBooks).forEach(System.out::println);
        authors.stream().flatMap(author -> author.getBooks().stream()).distinct().forEach(System.out::println);
    }

    private static void test09() {
        // 打印除了年龄最大的作家外的其他作家，要求不能有重复 元素，并且按照年龄降序排序
        List<Author> authors = getAuthors();
        authors.stream().distinct().sorted().skip(1).forEach(author -> System.out.println(author.getName()));
    }

    private static void test08() {
        // 对流中的元素按照年龄进行降序排序，并且要求不能有重复的元素，然后打印其中年龄最大的两个作家的姓名
        List<Author> authors = getAuthors();
        authors.stream().distinct()
                .sorted((o1, o2) -> o2.getAge() - o1.getAge())
                .limit(10)
                .forEach(author -> System.out.println(author.getName()));
    }

    private static void test07() {
        List<Author> authors = getAuthors();
        // 对流中的元素按照年龄进行降序排序，并且要求不能有重复的元素
        // 如果调用空参的sorted()方法，需要流中的元素是实现了Comparable，，此处是在Author中实现
//        authors.stream().distinct().sorted().forEach(author -> System.out.println(author.getAge()));
        authors.stream().distinct().sorted((o1, o2) -> o2.getAge() - o1.getAge()).forEach(author -> System.out.println(author.getAge()));

    }

    private static void test06() {
        // 打印作家的姓名，并且要求其中不能有重复的元素
        List<Author> authors = getAuthors();
//        authors.stream().distinct().forEach(author -> System.out.println(author.getName()));
        authors.stream().distinct().map(Author::getName).forEach(System.out::println);
    }

    private static void test05() {
        // 打印所有作家的姓名
        List<Author> authors = getAuthors();
        // 之前学的
//        authors.stream().forEach(author -> System.out.println(author.getName()));
//        authors.stream().map(author -> author.getName()).forEach(s -> System.out.println(s));
        authors.stream().map(author -> author.getAge() + 10).forEach(age -> System.out.println(age));

    }

    private static void test04() {
        // 打印所有姓名长度大于1的作家姓名
        List<Author> authors = getAuthors();
        authors.stream()
                .filter(author -> author.getName().length() > 1)
                .forEach(author -> System.out.println(author.getName()));
    }

    /**
     * map转换成流
     */
    private static void test03() {
        Map<String, Integer> map = new HashMap<>();
        map.put("蜡笔小新", 19);
        map.put("黑子", 17);
        map.put("日向洋", 16);

        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Stream<Map.Entry<String, Integer>> stream = entries.stream();
        stream.filter(entry -> entry.getValue() > 16)
                .forEach(entry -> System.out.println(entry.getKey() + "===" + entry.getValue()));

    }

    /**
     * 数组转换成流
     */
    private static void test02() {
        Integer[] arr = {1, 2, 3, 4, 5};
//        Stream<Integer> stream = Arrays.stream(arr);
        Stream<Integer> stream = Stream.of(arr);
        stream.distinct()
                .filter(integer -> integer > 2)
                .forEach(integer -> System.out.println(integer));
    }

    private static void test01(List<Author> authors) {
        authors.stream()//把集合转换成流
                .distinct()//排除重复元素
                .filter(author -> {
                    System.out.println("test");
                    return author.getAge() < 18;
                })// 过滤出年龄小于18的集合
                .forEach(author -> System.out.println(author.getName()));// 遍历打印
    }

    private static void test00(List<Author> authors) {
        List<Author> list = authors.stream()
                .distinct()
                .filter(author -> {
                    System.out.println(author.getName().contains("梦多"));
                    return author.getName().contains("梦多");
                })
                .collect(Collectors.toList());
        System.out.println(list);

    }

    private static List<Author> getAuthors() {
        // 初始化数据
        Author author1 = new Author(1L, "梦多", 33, "梦族", null);
        Author author2 = new Author(2L, "呀拉索", 22, "青藏高原", null);
        Author author3 = new Author(3L, "易", 14, "梦族", null);
        Author author4 = new Author(3L, "易", 14, "梦族", null);

        // 书籍列表
        List<Book> books1 = new ArrayList<>();
        List<Book> books2 = new ArrayList<>();
        List<Book> books3 = new ArrayList<>();

//        books1.add(new Book(1L, "刀", "哲学，爱情", 88, "一刀两断"));
//        books1.add(new Book(2L, "一个人刀", "个人成长，爱情", 99, "失败刀"));
//
//        books2.add(new Book(3L, "风", "哲学", 85, "思维"));
//        books2.add(new Book(3L, "风", "哲学", 85, "思维"));
//        books2.add(new Book(4L, "吹不吹", "爱情，个人传记", 56, "哲学家的恋爱观"));
//
//        books3.add(new Book(5L, "剑", "爱情", 56, "武者"));
//        books3.add(new Book(6L, "风剑", "个人传记", 100, "膨胀"));
//        books3.add(new Book(6L, "风剑", "个人传记", 100, "膨胀"));

        author1.setBooks(books1);
        author2.setBooks(books2);
        author3.setBooks(books3);
        author4.setBooks(books3);

        List<Author> authorList = new ArrayList<>(Arrays.asList(author1, author2, author3, author4));
        return authorList;
    }
}
